#ifndef _KZSHELL_H_
#define _KZSHELL_H_

#include <stdint.h>
#include "cppinc/nodelist.h"
#include <string>
#include "../common_typedef.h"
#include "cppinc/log.h"

#define SHELL_LEN_MAX 128
#define SHELL_HISTORY_CMD_NUM 5
#define SHELL_HISTORY_CMD_SZ 50
#define SHELL_MAX_PARAM_NUM 8
#define SHELL_PROMPT "kz> "

typedef int (*CliTaskCallBack)(uint8_t argc, char **argv);
typedef struct
{
    char cmd[SHELL_LEN_MAX];
    CliTaskCallBack exe;
} CmdPair;

enum keycode_t{
    PRINTABLE_KEY,
    ENTER,
    TAB,
    UP,
    DOWN,
    LEFT,
    RIGHT,
    BACKSPACE,
    DELETE,
    UNKNOWN
};

class kzshell {
public:
    kzshell() {};
    void RegCmd(std::string cmd, CliTaskCallBack exe);
    void CliProcByte(char ch);

private:
    keycode_t get_keycode(uint8_t c);
    void run_key_func(keycode_t x, char c);
    void print_prompt();
    int run_cmdline();
    void add_history_cmd();
    int complete();
    // special function key
    void normal_key_func(uint8_t c);
    void enter_key_func(uint8_t c);
    void tab_key_func(uint8_t c);
    void up_key_func(uint8_t c);
    void down_key_func(uint8_t c);
    void left_key_func(uint8_t c);
    void right_key_func(uint8_t c);
    void backspace_key_func(uint8_t c);
    void delete_key_func(uint8_t c);
    void unknown_key_func(uint8_t c);
    void dump_shell();

private:
    nodelist<std::string, CliTaskCallBack> m_cmdMap;
    char m_line[SHELL_LEN_MAX];
    char m_his_cmd[SHELL_HISTORY_CMD_NUM][SHELL_HISTORY_CMD_SZ];
    char m_shadow_line[SHELL_LEN_MAX];
    uint8_t m_cursor_pos = 0;
    uint8_t m_rcv_len = 0;
    uint8_t m_state = 0;
    uint8_t m_his_cmd_count = 0;
    uint8_t m_his_cmd_request_index = 0;
    uint8_t m_his_cmd_rear = 0;
};

#endif // _KZSHELL_H_